package com.twd.websocket;


import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.DefaultEventExecutor;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Chris Chan
 * Create on 2021/4/20 14:44
 * Use for:
 * Explain:
 */
public class ClientManager {
    //private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private static Map<Integer,ChannelGroup> channelGroup = new HashMap<Integer,ChannelGroup>();
    private static Map<ChannelId, String> userMap = new HashMap<>(16);
    public static Map<ChannelId, Integer> groupMap = new HashMap<>(16);

    public static ChannelGroup getChannelGroup(Integer sn) {

        return channelGroup.get(sn);
    }

    /**
     * 添加一个系统默认的channel
     *
     * @param username
     * @param channel
     */
    public static void addChannel(String username, Channel channel,int sn) {
        addWebsocketChannel(WebsocketChannel.create(username, channel),sn);
    }

    /**
     * 添加一个构建好的WebsocketChannel
     *
     * @param websocketChannel
     */
    public static void addWebsocketChannel(WebsocketChannel websocketChannel,int sn) {
        String username = websocketChannel.getUsername();

        if (null == username || "".equalsIgnoreCase(username.trim())) {
            throw new RuntimeException("username can not be empty.");
        }
        if (userMap.values().contains(username.trim())) {
            throw new RuntimeException("the username is exists.");
        }

        ChannelGroup group = channelGroup.get(sn);
        if(group!=null){
            group.add(websocketChannel);
            channelGroup.put(sn,group);

        }else{
            DefaultChannelGroup cg = new DefaultChannelGroup(new DefaultEventExecutor());
            cg.add(websocketChannel);
            channelGroup.put(sn,cg);
        }


        userMap.put(websocketChannel.id(), username.trim());
        groupMap.put(websocketChannel.id(),sn);
    }

    /**
     * 查找Channel
     *
     * @param channel
     * @return
     */
    public static WebsocketChannel find(Channel channel) {
        return find(channel.id());
    }

    /**
     * 查找Channel
     *
     * @param channelId
     * @return
     */
    public static WebsocketChannel find(ChannelId channelId) {
        Integer sn = groupMap.get(channelId);
        ChannelGroup group = channelGroup.get(sn);
        Channel channel = group.find(channelId);
        if (channel instanceof WebsocketChannel) {
            return (WebsocketChannel) channel;
        } else {
            return null;
        }
    }

    /**
     * 获取用户名
     *
     * @param channel
     * @return
     */
    public static String getUsername(Channel channel) {
        return getUsername(channel.id());
    }

    /**
     * 获取用户名
     *
     * @param channelId
     * @return
     */
    public static String getUsername(ChannelId channelId) {
        WebsocketChannel websocketChannel = find(channelId);
        String username;
        if (null == websocketChannel) {
            String val = userMap.get(channelId);
            if (null == val || "".equalsIgnoreCase(val)) {
                username = "unknown";
            } else {
                username = val;
            }
        } else {
            username = websocketChannel.getUsername();
        }
        return username;
    }

    /**
     * 移除Channel
     *
     * @param channel
     */
    public static void removeChannel(Channel channel) {
        removeChannel(channel.id());
    }

    /**
     * 根据ChannelId移除Channel
     *
     * @param channelId
     */
    public static void removeChannel(ChannelId channelId) {
        Integer gid = groupMap.get(channelId);
        ChannelGroup group = channelGroup.get(gid);
        Channel channel = group.find(channelId);
        if (null == channel) {
            userMap.remove(channelId);
            return;
        }
        if (channel instanceof WebsocketChannel) {
            removeWebsocketChannel((WebsocketChannel) channel);
        } else {
            group.remove(channel);
        }
    }

    /**
     * 移除WebsocketChannel
     *
     * @param websocketChannel
     */
    public static void removeWebsocketChannel(WebsocketChannel websocketChannel) {
        ChannelGroup group = channelGroup.get(groupMap.get(websocketChannel.id()));
        if (null == group || !group.contains(websocketChannel)) {
            return;
        }
        ChannelId channelId = websocketChannel.id();
        group.remove(websocketChannel);
        if (userMap.containsKey(channelId)) {
            userMap.remove(channelId);
        }
        if (groupMap.containsKey(channelId)) {
            groupMap.remove(channelId);
        }
    }

    /**
     * 客户端总数
     *
     * @return
     */
    public static int size() {
        return channelGroup.size();
    }

    /**
     * 群发消息
     *
     * @param msg
     */
    public static void send(String msg,ChannelId sn) {
        Integer gid = groupMap.get(sn);
        ChannelGroup group = channelGroup.get(gid);
        group.writeAndFlush(new TextWebSocketFrame(msg));
    }
}